﻿using System;
using System.Threading.Tasks;
using System.Collections.Generic;

using MyCtp;
using MyCtp.Model;

using WfhTrader.Core.Entity;
using WfhTrader.Core.Trading;

using WAF.EntityFramework;

namespace WfhTrader.Core.Quote
{
    /// <summary>
    /// 行情数据接口操作类
    /// </summary>
    public class CtpQuote
    {
        /// <summary>
        /// 初始化并异步运行行情数据接口
        /// </summary>
        /// <param name="account">CTP账户</param>
        public CtpQuote(WfhTrader.Core.Trading.CtpAccount account, string[] instruments)
        {
            this.ctpAccount = account;

            if (instruments != null)
            {
                //取得新的订阅行情列表
                subscribedInstruments = new string[instruments.Length];
                instruments.CopyTo(subscribedInstruments, 0);
            }

            Init();
        }

        /// <summary>
        /// 重新订阅行情
        /// </summary>
        /// <param name="instruments">订阅行情的合约列表</param>
        public void ReSubscribeMarketData(string[] instruments)
        {
            //只有登录成功后才能订阅行情
            if (isLogin)
            {
                //取消先前订阅的行情
                if (subscribedInstruments != null)
                    ctpMdApi.UnSubscribeMarketData(subscribedInstruments, subscribedInstruments.Length);

                if (instruments != null)
                {
                    //取得新的订阅行情列表
                    subscribedInstruments = new string[instruments.Length];
                    instruments.CopyTo(subscribedInstruments, 0);

                    //订阅新的行情列表
                    ctpMdApi.SubscribeMarketData(subscribedInstruments, subscribedInstruments.Length);
                }
            }
        }

        /// <summary>
        /// 释放行情接口对象
        /// </summary>
        public void Release()
        {
            ctpMdApi.Release();
        }


        /**************************** Private ****************************/

        /// <summary>
        /// 行情数据接口对象
        /// </summary>
        private MyCtp.CtpMdApi ctpMdApi;

        /// <summary>
        /// CTP账号
        /// </summary>
        private WfhTrader.Core.Trading.CtpAccount ctpAccount;

        /// <summary>
        /// 请求序号
        /// </summary>
        private int requestID = 0;

        /// <summary>
        /// 是否已经登录成功
        /// </summary>
        private bool isLogin = false;

        /// <summary>
        /// 订阅行情的合约列表
        /// </summary>
        private string[] subscribedInstruments;


        /// <summary>
        /// 初始化并运行行情数据接口
        /// </summary>
        private void Init()
        {
            //初始化接口对象并注册前置机地址
            ctpMdApi = new CtpMdApi();

            //从数据库中读取前置机地址
            WAF.DAO.DbParameters parameters = new WAF.DAO.DbParameters();
            parameters.Add("@Purpose", (int)this.ctpAccount.PurposeType, System.Data.DbType.Int32);
            parameters.Add("@Type", (int)FrontType.Quote, System.Data.DbType.Int32);
            CtpFrontAddress[] fronts = EntityAction.Select<CtpFrontAddress>("SELECT Address FROM CtpFrontAddress WHERE Purpose=@Purpose AND Type=@Type", parameters);

            //注册前置机地址
            foreach (CtpFrontAddress front in fronts)
                ctpMdApi.RegisterFront(front.Address);

            //注册接口回调事件
            ctpMdApi.CtpMdEvents.OnFrontConnected       += this.OnFrontConnected;
            ctpMdApi.CtpMdEvents.OnRspUserLogin         += this.OnRspUserLogin;
            ctpMdApi.CtpMdEvents.OnRspSubMarketData     += this.OnRspSubMarketData;
            ctpMdApi.CtpMdEvents.OnRtnDepthMarketData   += this.OnRtnDepthMarketData;

            //初始化并运行
            ctpMdApi.Init();
            Task.Factory.StartNew(ctpMdApi.Join);
        }

        /// <summary>
        /// 连接前置机并登录
        /// </summary>
        private void OnFrontConnected()
        {
            CThostFtdcReqUserLoginField loginField = new CThostFtdcReqUserLoginField();

            loginField.BrokerID = this.ctpAccount.Broker.Code;
            loginField.UserID   = this.ctpAccount.AccountNumber;
            loginField.Password = this.ctpAccount.Password;

            ctpMdApi.ReqUserLogin(loginField, requestID++);
        }

        /// <summary>
        /// 用户登录应答
        /// </summary>
        private void OnRspUserLogin(CThostFtdcRspUserLoginField rspUserLoginfield, CThostFtdcRspInfoField rspInfoField, int nRequestID, bool bIsLast)
        {
            //登录成功则订阅行情
            if (rspInfoField.ErrorID == 0 && subscribedInstruments != null)
            {
                isLogin = true;
                ctpMdApi.SubscribeMarketData(subscribedInstruments, subscribedInstruments.Length);
            }
        }

        /// <summary>
        /// 无用
        /// </summary>
        private void OnRspSubMarketData(CThostFtdcSpecificInstrumentField pSpecificInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        /// <summary>
        /// 发布最新行情数据
        /// </summary>
        /// <param name="pDepthMarketData">深度行情数据结构</param>
        private void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData)
        {
            if (pDepthMarketData != null)
            {
                QuoteData quote = new QuoteData();

                quote.MarketType    = MarketType.Futures;
                quote.Code          = pDepthMarketData.InstrumentID;
                quote.Price         = pDepthMarketData.LastPrice;
                quote.UpdateTime    = DateTime.Parse(pDepthMarketData.UpdateTime);

                QuoteManager.GetInstance().EnqueueQuote(quote);
            }
        }
    }
}
